#include "system.hpp"

/************ System resources. ************/

RCCRegister_t *rcc_register = (RCCRegister_t*)0x40023800;
GPIORegister_t *gpio_a_register = (GPIORegister_t*)0x40020000;
GPIORegister_t *gpio_b_register = (GPIORegister_t*)0x40020400;
GPIORegister_t *gpio_c_register = (GPIORegister_t*)0x40020800;
GPIORegister_t *gpio_d_register = (GPIORegister_t*)0x40020c00;
GPIORegister_t *gpio_e_register = (GPIORegister_t*)0x40021000;
GPIORegister_t *gpio_h_regsiter = (GPIORegister_t*)0x40021c00;



extern "C" void System_init(void){
    
}

bool System::setClockChannelStatus(ClockChannel channel,bool status){
    int channel_index = (int)channel;
    int bus = channel_index / 32;
    int bus_bit = channel_index % 32;
    if ( status ){
        switch ( bus ){
            case 0: /* AHB1. */
                rcc_register->AHB1ENR |= (0x01 << bus_bit);
                break;
            case 1: /* AHB2. */
                rcc_register->AHB2ENR |= (0x01 << bus_bit);
                break;
            case 2: /* APB1. */
                rcc_register->APB1ENR |= (0x01 << bus_bit);
                break;
            case 3: /* APB2. */
                rcc_register->APB2ENR |= (0x01 << bus_bit);
                break;
        }
    }else{
        switch ( bus ){
            case 0: /* AHB1. */
                rcc_register->AHB1ENR &= ~(0x01 << bus_bit);
                break;
            case 1: /* AHB2. */
                rcc_register->AHB2ENR &= ~(0x01 << bus_bit);
                break;
            case 2: /* APB1. */
                rcc_register->APB1ENR &= ~(0x01 << bus_bit);
                break;
            case 3: /* APB2. */
                rcc_register->APB2ENR &= ~(0x01 << bus_bit);
                break;
        }
    }
    
}

bool System::getClockChannelStatus(ClockChannel channel){
    int channel_index = (int)channel;
    int bus = channel_index / 32;
    int bus_bit = channel_index % 32;
    uint32_t reg_mask;
    switch ( bus ){
        case 0: /* AHB1. */
            reg_mask = rcc_register->AHB1ENR & (0x01 << bus_bit);
            break;
        case 1: /* AHB2. */
            reg_mask = rcc_register->AHB2ENR & (0x01 << bus_bit);
            break;
        case 2: /* APB1. */
            reg_mask = rcc_register->APB1ENR & (0x01 << bus_bit);
            break;
        case 3: /* APB2. */
            reg_mask = rcc_register->APB2ENR & (0x01 << bus_bit);
            break;
    }
    if ( reg_mask != 0x00000000 ){
        return true;
    }else{
        return false;
    }
}